#include "Cmaid_Gtest.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

TEST_P(Cmaid_List_Gtest, count_append)
{
	int i;

	for (i = 0; i < 1000; i++)
	{
		ASSERT_EQ(i, cmaid_container_count(list));
		cmaid_list_append(list, dataAt(0));
	}
}

TEST_P(Cmaid_List_Gtest, count_prepend)
{
	int i;

	for (i = 0; i < 1000; i++)
	{
		ASSERT_EQ(i, cmaid_container_count(list));
		cmaid_list_prepend(list, dataAt(0));
	}
}

TEST_P(Cmaid_List_Gtest, prepend)
{
	int i;

	for (i = 0; i < dataCount(); i++)
	{
		void *data;
		cmaid_list_prepend(list, dataAt(i));

		data = cmaid_list_first(list);
		/* if there is no data return fail */
		ASSERT_TRUE(NULL != data) << " i == " << i;
		ASSERT_DATA_EQ(dataAt(i), data) << " i == " << i;
		if (isPointerType())
			ASSERT_EQ(dataAt(i), data) << " i == " << i;
		else
			ASSERT_NE(dataAt(i), data) << " i == " << i;
	}
}

TEST_P(Cmaid_List_Gtest, append)
{
	int i;

	for (i = 0; i < dataCount(); i++)
	{
		void *data;
		cmaid_list_append(list, dataAt(i));

		data = cmaid_list_last(list);
		/* if there is no data return fail */
		ASSERT_TRUE(NULL != data);
		ASSERT_DATA_EQ(dataAt(i), data);
		if (isPointerType())
			ASSERT_EQ(dataAt(i), data);
		else
			ASSERT_NE(dataAt(i), data);
	}
}

TEST_P(Cmaid_List_Gtest, first_remove)
{
	int i;

	fill();
	
	for (i = 0; i < dataCount(); i++)
	{
		void *name = cmaid_list_first(list);

		ASSERT_DATA_EQ(dataAt(i), name);
		cmaid_list_first_remove(list);
		ASSERT_EQ(dataCount() - i - 1, cmaid_container_count(list));
	}
}

TEST_P(Cmaid_List_Gtest, last_remove)
{
	int i;

	for (i = 0; i < dataCount(); i++)
		cmaid_list_append(list, dataAt(i));
	
	for (i = 0; i < dataCount(); i++)
	{
		void *name = cmaid_list_first(list);
		ASSERT_DATA_EQ(dataAt(i), name);
		cmaid_list_first_remove(list);
		ASSERT_EQ(dataCount() - i - 1, cmaid_container_count(list));
	}
}

TEST_P(Cmaid_List_Gtest, clear)
{
	int i;
	void *data;

	/* first clear an empty list, I know that seems to be non-sense
	 * but maybe we trigger a hidden bug */
	cmaid_container_clear(list);
	ASSERT_EQ(0, cmaid_container_count(list));
	data = cmaid_list_first(list);
	ASSERT_TRUE(NULL == data);
	data = cmaid_list_last(list);
	ASSERT_TRUE(NULL == data);

	for (i = 0; i < dataCount(); i++)
		cmaid_list_append(list, dataAt(i));
	
	/* and now do the same with a filled list */
	cmaid_container_clear(list);
	ASSERT_EQ(0, cmaid_container_count(list));
	data = cmaid_list_first(list);
	ASSERT_TRUE(NULL == data);
	data = cmaid_list_last(list);
	ASSERT_TRUE(NULL == data);
}

TEST_P(Cmaid_List_Gtest, dump)
{
	Cmaid_Iter iter __CMAID_CHECKED_ITER__;
	FILE *file;
	void *data;
	int size;

	/* Of course we cannot test the output of dump here without
	 * writing an disproportional difficult parser. So we only test
	 * it to see if it segfault and do some alibi tests */
	fill();
	cmaid_container_iter_attach(list, &iter);
	data = cmaid_iter_index_goto(&iter, 3);
	size = cmaid_container_count(list);

	file = tmpfile();
	cmaid_container_dump(list, file);
	fclose(file);

	ASSERT_EQ(size, cmaid_container_count(list));
	ASSERT_DATA_EQ(data, cmaid_iter_current(&iter));
	ASSERT_EQ(3, cmaid_iter_index_get(&iter));
	
	cmaid_container_iter_detach(list, &iter);
}

TEST_P(Cmaid_List_Gtest, empty)
{
	void *data;

	ASSERT_EQ(0, cmaid_container_count(list));
	data = cmaid_list_first(list);
	ASSERT_TRUE(NULL == data);
	data = cmaid_list_last(list);
	ASSERT_TRUE(NULL == data);
}

TEST_P(Cmaid_List_Gtest, iter_first)
{
	Cmaid_Iter it;
	void *i_first, *c_first;

	fill();

	cmaid_container_iter_attach(list, &it);
	i_first = cmaid_iter_next(&it);
	c_first = cmaid_list_first(list);
	ASSERT_EQ(i_first, c_first);
	ASSERT_DATA_EQ(dataAt(0), i_first);
	ASSERT_EQ(0, cmaid_iter_index_get(&it));

	/* and now clear the list */
	cmaid_container_clear(list);
	i_first = cmaid_iter_current(&it);
	ASSERT_TRUE(NULL == i_first);
	ASSERT_GT(0, cmaid_iter_index_get(&it));
	
	cmaid_container_iter_detach(list, &it);
}

TEST_P(Cmaid_List_Gtest, iter_last)
{
	Cmaid_Iter it;
	void *i_last, *c_last;

	fill();

	cmaid_container_iter_attach(list, &it);
	i_last = cmaid_iter_previous(&it);
	c_last = cmaid_list_last(list);
	ASSERT_EQ(i_last, c_last);
	ASSERT_DATA_EQ(dataAt(dataCount() - 1), i_last);
	ASSERT_EQ(dataCount() - 1, cmaid_iter_index_get(&it));

	/* and now clear the list */
	cmaid_container_clear(list);
	i_last = cmaid_iter_current(&it);
	ASSERT_TRUE(NULL == i_last);
	ASSERT_GT(0, cmaid_iter_index_get(&it));
	
	cmaid_container_iter_detach(list, &it);
}

TEST_P(Cmaid_List_Gtest, iter_next)
{
	Cmaid_Iter it;
	int i = 0;
	void *name;

	fill();

	cmaid_container_iter_attach(list, &it);
	while ((name = cmaid_iter_next(&it)))
	{
		ASSERT_DATA_EQ(dataAt(i), name);
		if (i < dataCount())
			ASSERT_EQ(i, cmaid_iter_index_get(&it));
		i++;
	}
	ASSERT_EQ(i, dataCount());
	cmaid_container_iter_detach(list, &it);
}

TEST_P(Cmaid_List_Gtest, iter_previous)
{
	Cmaid_Iter it;
	int i = dataCount() - 1;
	void *name;

	fill();

	cmaid_container_iter_attach(list, &it);
	cmaid_iter_start(&it);
	while ((name = cmaid_iter_previous(&it)))
	{
		ASSERT_DATA_EQ(dataAt(i), name);
		if (i > 0)
			ASSERT_EQ(i, cmaid_iter_index_get(&it));
		i--;
	}
	ASSERT_GT(0, i);
	cmaid_container_iter_detach(list, &it);
}

TEST_P(Cmaid_List_Gtest, iter_index_goto)
{
	Cmaid_Iter it;
	int i;
	void *name;

	fill();

	cmaid_container_iter_attach(list, &it);
	for (i = 0; i < dataCount(); i++)
	{
		const int j = dataCount() - i - 1;

		name = cmaid_iter_index_goto(&it, i);
		ASSERT_TRUE(NULL != name);
		ASSERT_DATA_EQ(dataAt(i), name);
		ASSERT_EQ(i, cmaid_iter_index_get(&it));
		
		cmaid_iter_index_goto(&it, j);
		name = cmaid_iter_current(&it);
		ASSERT_TRUE(NULL != name);
		ASSERT_DATA_EQ(dataAt(j), name);
		ASSERT_EQ(j, cmaid_iter_index_get(&it));
	}
	cmaid_container_iter_detach(list, &it);
}

TEST_P(Cmaid_List_Gtest, iter_goto)
{
	Cmaid_Iter it;
	Cmaid_Iter it2;
	int i;
	void *name;

	fill();

	cmaid_container_iter_attach(list, &it);
	cmaid_container_iter_attach(list, &it2);
	for (i = 0; i < dataCount(); i++)
	{
		const int j = dataCount() - i - 1;
		void *data;

		/* first find the data pointer */
		for (cmaid_iter_start(&it2);
			(data = cmaid_iter_next(&it2)) &&
			!dataEquals(cmaid_iter_current(&it2), dataAt(i));)
			;
		/* and now find it again in the list */
		name = cmaid_iter_goto(&it, data);
		ASSERT_TRUE(NULL != name);
		ASSERT_DATA_EQ(dataAt(i), name);
		ASSERT_EQ(i, cmaid_iter_index_get(&it));
		
		for (cmaid_iter_start(&it2);
			(data = cmaid_iter_next(&it2)) &&
			!dataEquals(cmaid_iter_current(&it2), dataAt(j));)
			;
		cmaid_iter_goto(&it, data);
		name = cmaid_iter_current(&it);
		ASSERT_TRUE(NULL != name);
		ASSERT_TRUE(data == name);
		ASSERT_EQ(j, cmaid_iter_index_get(&it));
	}
	cmaid_container_iter_detach(list, &it);
	cmaid_container_iter_detach(list, &it2);
}

TEST_P(Cmaid_List_Gtest, iter_detach)
{
	Cmaid_Iter it;
	int index;
	int i;

	fill();

	for (i = 0; i < dataCount()/2; i++)
	{
		cmaid_container_iter_attach(list, &it);
		cmaid_iter_index_goto(&it, i);
		cmaid_container_iter_detach(list, &it);
		/* this might be i or something else, this is not defined */
		index = it.index;

		/* no we remove the first node, if the iterator would be still
		 * attached the index must be changed, since it isn't it the
		 * indeces must be the same */
		cmaid_list_first_remove(list);
		ASSERT_EQ(index, it.index);
	}
}

TEST_P(Cmaid_List_Gtest, iter_iter_goto)
{
	int i;

	fill();

	for (i = 0; i < dataCount(); i++)
	{
		Cmaid_Iter it1, it2;
		void *ret;

		cmaid_container_iter_attach(list, &it1);
		cmaid_container_iter_attach(list, &it2);

		/* Go now with the first iterator to the i-th node */
		cmaid_iter_index_goto(&it1, i);
		/* let's see if the other iter will follow */
		ret = cmaid_iter_iter_goto(&it2, &it1);
		ASSERT_TRUE(NULL != ret);
		
		ASSERT_TRUE(NULL != cmaid_iter_current(&it2));
		ASSERT_EQ(cmaid_iter_current(&it1), cmaid_iter_current(&it2));
		ASSERT_EQ(cmaid_iter_index_get(&it1), cmaid_iter_index_get(&it2));
		/* although we've already test that in another test we can do
		 * it again */
		ret = cmaid_iter_current(&it2);
		ASSERT_TRUE(NULL != ret);
		ASSERT_DATA_EQ(dataAt(i), ret);
		
		cmaid_container_iter_detach(list, &it1);
		cmaid_container_iter_detach(list, &it2);
	}
}

TEST_P(Cmaid_List_Gtest, first_remove_with_iters)
{
	int index;

	for (index = 0; index < dataCount(); index++)
	{
		Cmaid_Iter it[6];
		int i, N = sizeof(it)/sizeof(Cmaid_Iter);

		fill();
		/* just to be sure our test is correct */
		ASSERT_EQ(dataCount(), cmaid_container_count(list));

		for (i = 0; i < N; i++)
		{
			cmaid_container_iter_attach(list, &it[i]);
			cmaid_iter_index_goto(&it[i], index);
		}

		/* no we remove the first node, since the iterator is still
		 * attached the index must be changed if we are not at
		 * position 0 */
		cmaid_list_first_remove(list);
		for (i = 0; i < N; i++)
		{
			if (index == 0)
				ASSERT_ITER_IS(&it[i], -1, NULL);
			/* the index changed, but we should still point to the 
			 * same data */
			else
				ASSERT_ITER_IS(&it[i], index - 1, dataAt(index));

			cmaid_container_iter_detach(list, &it[i]);
		}
		cmaid_container_clear(list);
	}
}

TEST_P(Cmaid_List_Gtest, last_remove_with_iters)
{
	int index;

	for (index = 0; index < dataCount(); index++)
	{
		Cmaid_Iter it[6];
		int i, N = sizeof(it)/sizeof(Cmaid_Iter);

		fill();
		/* just to be sure our test is correct */
		ASSERT_EQ(dataCount(), cmaid_container_count(list));

		for (i = 0; i < N; i++)
		{
			cmaid_container_iter_attach(list, &it[i]);
			cmaid_iter_index_goto(&it[i], index);
		}

		/* here we remove the last node, since the iterator are before
		 * the last node, except for the index == dataCount() - 1 case,
		 * nothing should be changed there */
		cmaid_list_last_remove(list);
		for (i = 0; i < N; i++)
		{
			if (index == dataCount() - 1)
				ASSERT_ITER_IS(&it[i], index - 1,
						dataAt(index - 1));
			else
				ASSERT_ITER_IS(&it[i], index, dataAt(index));

			cmaid_container_iter_detach(list, &it[i]);
		}
		cmaid_container_clear(list);
	}
}

TEST_P(Cmaid_List_Gtest, iter_remove)
{
	int index;

	for (index = 0; index < dataCount(); index++)
	{
		Cmaid_Iter it, it_last, it_first;

		fill();
		/* just to be sure our test is correct */
		ASSERT_EQ(dataCount(), cmaid_container_count(list));

		cmaid_container_iter_attach(list, &it);
		cmaid_iter_index_goto(&it, index);

		cmaid_container_iter_attach(list, &it_last);
		cmaid_iter_previous(&it_last);

		cmaid_container_iter_attach(list, &it_first);
		cmaid_iter_next(&it_first);

		/* we will now remove the node, on which it is pointing to. */
		cmaid_iter_remove(&it);

		/* if we are on the first node the index is index - 1  and the
		 * data is null*/
		if (index == 0)
			ASSERT_ITER_IS(&it, -1, NULL);
		/* else the index should be less - 1 and the data is the
		 * previous name */
		else
			ASSERT_ITER_IS(&it, index - 1, dataAt(index - 1));

		/* let's see what happen with the iterator to the first
		 * element */
		if (index == 0)
			ASSERT_ITER_IS(&it_first, -1, NULL);
		else
			ASSERT_ITER_IS(&it_first, 0, dataAt(0));
		
		/* and the last iter */
		if (index == dataCount() - 1)
			ASSERT_ITER_IS(&it_last, dataCount() - 2,
					dataAt(dataCount() - 2));
		else
			ASSERT_ITER_IS(&it_last, dataCount() - 2,
					dataAt(dataCount() - 1));

		cmaid_container_iter_detach(list, &it);
		cmaid_container_iter_detach(list, &it_last);
		cmaid_container_iter_detach(list, &it_first);

		cmaid_container_clear(list);
	}
}

TEST_P(Cmaid_List_Gtest, insert_after)
{
	Cmaid_Iter it1 __CMAID_CHECKED_ITER__;
	Cmaid_Iter it2 __CMAID_CHECKED_ITER__;
	Cmaid_Iter it3 __CMAID_CHECKED_ITER__;
	Cmaid_Iter it4 __CMAID_CHECKED_ITER__;
	int i;

	cmaid_list_append(list, dataAt(0));
	cmaid_container_iter_attach(list, &it1);
	cmaid_container_iter_attach(list, &it2);
	cmaid_container_iter_attach(list, &it3);
	cmaid_container_iter_attach(list, &it4);
	cmaid_iter_next(&it4);

	for (i = 1; i < dataCount(); i++)
	{
		void *ret;

		cmaid_iter_index_goto(&it3, 0);
		cmaid_list_insert_after(list, &it2, dataAt(i));

		ASSERT_EQ(-1, cmaid_iter_index_get(&it1));
		ASSERT_TRUE(NULL == cmaid_iter_current(&it1));
		ASSERT_EQ(-1, cmaid_iter_index_get(&it2));
		ASSERT_TRUE(NULL == cmaid_iter_current(&it2));
		ASSERT_EQ(1, cmaid_iter_index_get(&it3));
		ASSERT_EQ(i, cmaid_iter_index_get(&it4));
		ASSERT_DATA_EQ(dataAt(0), cmaid_iter_current(&it4));
		
		ret = cmaid_iter_next(&it2);
		ASSERT_TRUE(NULL != ret);
		ASSERT_DATA_EQ(dataAt(i), ret);
		cmaid_iter_start(&it2);

		cmaid_iter_next(&it1);
		ASSERT_EQ(0, cmaid_iter_index_get(&it1));
		cmaid_iter_next(&it1);
		ASSERT_EQ(1, cmaid_iter_index_get(&it1));

		ASSERT_DATA_EQ(cmaid_iter_current(&it1),
				cmaid_iter_current(&it3));
		cmaid_iter_start(&it1);
	}
	cmaid_container_iter_detach(list, &it1);
	cmaid_container_iter_detach(list, &it2);
	cmaid_container_iter_detach(list, &it3);
	cmaid_container_iter_detach(list, &it4);
}

TEST_P(Cmaid_List_Gtest, insert_after2)
{
	Cmaid_Iter it1 __CMAID_CHECKED_ITER__;
	Cmaid_Iter it2 __CMAID_CHECKED_ITER__;
	Cmaid_Iter it3 __CMAID_CHECKED_ITER__;
	Cmaid_Iter it4 __CMAID_CHECKED_ITER__;
	int i;

	cmaid_list_append(list, dataAt(0));
	cmaid_list_prepend(list, dataAt(1));
	cmaid_container_iter_attach(list, &it1);
	cmaid_iter_index_goto(&it1, 0);
	cmaid_container_iter_attach(list, &it2);
	cmaid_container_iter_attach(list, &it3);
	cmaid_container_iter_attach(list, &it4);
	cmaid_iter_index_goto(&it4, 1);

	for (i = 2; i < dataCount(); i++)
	{
		void *ret;

		cmaid_iter_index_goto(&it2, i - 2);
		cmaid_iter_index_goto(&it3, i - 2);
		cmaid_list_insert_after(list, &it2, dataAt(i));

		ASSERT_EQ(0, cmaid_iter_index_get(&it1));
		ASSERT_EQ(i - 2, cmaid_iter_index_get(&it2));
		ASSERT_EQ(i - 2, cmaid_iter_index_get(&it3));
		ASSERT_EQ(i, cmaid_iter_index_get(&it4));
		ASSERT_DATA_EQ(dataAt(0), cmaid_iter_current(&it4));
		
		ret = cmaid_iter_next(&it2);
		ASSERT_TRUE(NULL != ret);
		ASSERT_DATA_EQ(dataAt(i), ret);
		cmaid_iter_start(&it2);
	}
	cmaid_container_iter_detach(list, &it1);
	cmaid_container_iter_detach(list, &it2);
	cmaid_container_iter_detach(list, &it3);
	cmaid_container_iter_detach(list, &it4);
}

TEST_P(Cmaid_List_Gtest, insert_before)
{
	Cmaid_Iter it1 __CMAID_CHECKED_ITER__;
	Cmaid_Iter it2 __CMAID_CHECKED_ITER__;
	Cmaid_Iter it3 __CMAID_CHECKED_ITER__;
	Cmaid_Iter it4 __CMAID_CHECKED_ITER__;
	int i;

	cmaid_list_append(list, dataAt(0));
	cmaid_container_iter_attach(list, &it1);
	cmaid_container_iter_attach(list, &it2);
	cmaid_container_iter_attach(list, &it3);
	cmaid_container_iter_attach(list, &it4);
	cmaid_iter_next(&it4);

	for (i = 1; i < dataCount(); i++)
	{
		void *ret;

		cmaid_iter_index_goto(&it3, 0);
		cmaid_list_insert_before(list, &it2, dataAt(i));

		ASSERT_EQ(-1, cmaid_iter_index_get(&it1));
		ASSERT_TRUE(NULL == cmaid_iter_current(&it1));
		ASSERT_EQ(-1, cmaid_iter_index_get(&it2));
		ASSERT_TRUE(NULL == cmaid_iter_current(&it2));
		ASSERT_EQ(0, cmaid_iter_index_get(&it3));
		ASSERT_EQ(0, cmaid_iter_index_get(&it4));
		ASSERT_DATA_EQ(dataAt(0), cmaid_iter_current(&it4));
		
		ret = cmaid_iter_previous(&it2);
		ASSERT_TRUE(NULL != ret);
		ASSERT_DATA_EQ(dataAt(i), ret);
		cmaid_iter_start(&it2);
	}
	cmaid_container_iter_detach(list, &it1);
	cmaid_container_iter_detach(list, &it2);
	cmaid_container_iter_detach(list, &it3);
	cmaid_container_iter_detach(list, &it4);
}

TEST_P(Cmaid_List_Gtest, insert_before2)
{
	Cmaid_Iter it1 __CMAID_CHECKED_ITER__;
	Cmaid_Iter it2 __CMAID_CHECKED_ITER__;
	Cmaid_Iter it3 __CMAID_CHECKED_ITER__;
	Cmaid_Iter it4 __CMAID_CHECKED_ITER__;
	int i;

	cmaid_list_append(list, dataAt(0));
	cmaid_container_iter_attach(list, &it1);
	cmaid_container_iter_attach(list, &it2);
	cmaid_container_iter_attach(list, &it3);
	cmaid_container_iter_attach(list, &it4);
	cmaid_iter_next(&it4);
	cmaid_iter_next(&it2);

	for (i = 1; i < dataCount(); i++)
	{
		void *ret;

		cmaid_iter_index_goto(&it3, i - 2);
		cmaid_list_insert_before(list, &it2, dataAt(i));

		ASSERT_EQ(-1, cmaid_iter_index_get(&it1));
		ASSERT_TRUE(NULL == cmaid_iter_current(&it1));
		ASSERT_EQ(i, cmaid_iter_index_get(&it2));
		ASSERT_DATA_EQ(dataAt(0), cmaid_iter_current(&it2));
		ASSERT_EQ(i - 2, cmaid_iter_index_get(&it3));
		ASSERT_EQ(i, cmaid_iter_index_get(&it4));
		ASSERT_DATA_EQ(dataAt(0), cmaid_iter_current(&it4));
		
		ret = cmaid_iter_previous(&it2);
		ASSERT_TRUE(NULL != ret);
		ASSERT_DATA_EQ(dataAt(i), ret);
		cmaid_iter_next(&it2);
	}
	cmaid_container_iter_detach(list, &it1);
	cmaid_container_iter_detach(list, &it2);
	cmaid_container_iter_detach(list, &it3);
	cmaid_container_iter_detach(list, &it4);
}

TEST_P(Cmaid_List_Gtest, sort)
{
	int i;
	Cmaid_Iter it;
	void *val1, *val2;

	/* fill the list */
	for (i = 0; i < dataCount(); i++)
		cmaid_list_append(list, dataAt(i));

	cmaid_list_sort(list);
	/* check, we need here iterators should there a problem with sorting
	 * _and_ with iterators, fix the problem with the iterators first */
	cmaid_container_iter_attach(list, &it);
	
	cmaid_iter_start(&it);
	val1 = cmaid_iter_next(&it);
	i = 0;
	while ((val2 = cmaid_iter_next(&it)))
	{
		ASSERT_TRUE(dataCompare(val1, val2) <= 0) << dataToString(val1)
			<< " <= " << dataToString(val2);
		
		val1 = val2;
		i++;
	}
	ASSERT_EQ(dataCount() - 1, i);

	cmaid_container_iter_detach(list, &it);
}

TEST_P(Cmaid_List_Gtest, sort_with)
{
	int i;
	Cmaid_Iter it;
	void *val1, *val2;

	/* fill the list */
	fill();

	cmaid_list_sort_with(list, dataCompareAltGet());
	/* check, we need here iterators should there a problem with sorting
	 * _and_ with iterators, fix the problem with the iterators first */
	cmaid_container_iter_attach(list, &it);
	
	cmaid_iter_start(&it);
	val1 = cmaid_iter_next(&it);
	i = 0;
	while ((val2 = cmaid_iter_next(&it)))
	{
		ASSERT_TRUE(dataCompareAlt(val1, val2) <= 0)
			<< dataToString(val1)
			<< " <= " << dataToString(val2);
		
		val1 = val2;
		i++;
	}
	ASSERT_EQ(dataCount() - 1, i);

	cmaid_container_iter_detach(list, &it);
}

TEST_P(Cmaid_List_Gtest, reverse)
{
	int i;
	Cmaid_Iter it;
	void *val;

	/* fill the list */
	for (i = 0; i < dataCount(); i++)
		cmaid_list_append(list, dataAt(i));

	cmaid_list_reverse(list);
	
	cmaid_container_iter_attach(list, &it);
	i = 0;
	while ((val = cmaid_iter_next(&it)))
	{
		ASSERT_DATA_EQ(dataAt(dataCount() - i - 1), val);
		i++;
	}
	ASSERT_EQ(i, dataCount());

	cmaid_container_iter_detach(list, &it);
}
	
